package com.diaohw.module.system.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.diaohw.module.system.mapper.*;
import com.diaohw.module.system.obj.entity.Account;
import com.diaohw.module.system.obj.entity.AccountRole;
import com.diaohw.module.system.obj.entity.Menu;
import com.diaohw.module.system.obj.entity.Role;
import com.diaohw.module.system.obj.mapstruct.*;
import com.diaohw.module.system.obj.query.AccountQuery;
import com.diaohw.module.system.service.AuthService;
import com.diaohw.platform.common.util.CryptoUtil;
import com.diaohw.platform.common.util.TreeUtil;
import com.diaohw.platform.remote.auth.obj.bo.*;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class AuthImpl implements AuthService {
    @Resource
    AccountMapper accountMapper;
    @Resource
    MenuMapper menuMapper;
    @Resource
    RoleMapper roleMapper;
    @Resource
    PermissionMapper permissionMapper;
    @Resource
    DepartmentMapper departmentMapper;
    @Resource
    private AccountRoleMapper accountRoleMapper;

    @Override
    public List<AccountSaltBO> username(String username) {
        AccountQuery query = new AccountQuery();
        query.setUsername(username);
        QueryWrapper wrapper = AccountMapper.createWrapper(query);
        return AccountMapstruct.INSTANCE.entityToSalt(accountMapper.selectListByQuery(wrapper));
    }

    @Override
    public AccountInfoBO info(String id) {
        Account account = accountMapper.selectOneById(id);
        QueryWrapper wrapper = QueryWrapper.create();
        wrapper.select(AccountRole::getRoleId);
        wrapper.eq(AccountRole::getAccountId, id);
        List<String> roleIds = accountRoleMapper.selectListByQueryAs(wrapper, String.class);
        // 角色
        List<RoleBO> roles = getRoles(roleIds);
        // 权限
        List<PermissionBO> permission = getPermission(roles);
        // 菜单
        List<MenuBO> menus = getMenus(roles);
        // 菜单树
        List<MenuBO> tree = TreeUtil.listToTree(menus, MenuBO::getId, MenuBO::getParentId, MenuBO::getChildren);

        DepartmentBO department = getDepartment(account.getDepartmentId());
        return AccountInfoBO.builder()
                .account(AccountMapstruct.INSTANCE.entityToBo(account))
                .department(department)
                .roles(roles)
                .menus(tree)
                .permissions(permission)
                .build();
    }


    /**
     * 部门信息
     *
     * @param deptId 部门ID
     */
    private DepartmentBO getDepartment(String deptId) {
        if (StrUtil.isNotBlank(deptId)) {
            return DepartmentMapstruct.INSTANCE.entityToBo(departmentMapper.selectOneById(deptId));
        }
        return null;
    }

    /**
     * 角色信息
     *
     * @param roleIds 角色ID集合
     */
    private List<RoleBO> getRoles(List<String> roleIds) {
        if (roleIds == null || roleIds.isEmpty()) {
            return List.of();
        }
        List<Role> roles = roleMapper.selectListByIds(roleIds);
        return roles
                .stream().map(RoleMapstruct.INSTANCE::entityToBo)
                .toList();
    }

    /**
     * 菜单信息
     *
     * @param roles 角色
     */
    private List<MenuBO> getMenus(List<RoleBO> roles) {
        if (roles == null || roles.isEmpty()) {
            return List.of();
        }
        List<String> menuIds = roles.stream().map(RoleBO::getMenuId)
                .flatMap((Function<List<String>, Stream<String>>) Collection::stream)
                .collect(Collectors.toList());
        if (menuIds.isEmpty()) {
            return List.of();
        }
        QueryWrapper wrapper = QueryWrapper.create();

        wrapper.in(Menu::getId, menuIds)
                .orderBy(Menu::getParentId, Boolean.TRUE)
                .orderBy(Menu::getSort, Boolean.TRUE);

        return MenuMapstruct.INSTANCE.entityToTreeBo(menuMapper.selectListByQuery(wrapper));
    }

    /**
     * 页面按钮权限
     *
     * @param roles 角色
     */
    private List<PermissionBO> getPermission(List<RoleBO> roles) {
        if (roles.isEmpty()) {
            return List.of();
        }
        List<String> permissionIds = roles.stream().map(RoleBO::getPermissionId)
                .flatMap((Function<List<String>, Stream<String>>) Collection::stream)
                .toList();
        if (permissionIds.isEmpty()) {
            return List.of();
        }
        return permissionMapper.selectListByIds(permissionIds)
                .stream().map(PermissionMapstruct.INSTANCE::entityToBo)
                .toList();
    }

    @Override
    public Boolean reset(PasswordBO password) {
        String salt = IdUtil.randomUUID();
        String pass = CryptoUtil.md5(salt, password.getPassword());
        Account account = new Account();
        account.setPassword(pass);
        account.setSalt(salt);
        account.setId(password.getAccountId());
        return accountMapper.update(account, Boolean.TRUE) > 0;
    }
}
